#include <unistd.h>
#include <strings.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <getopt.h>
#include <err.h>
#include "base64.h"


#define ENCODE_ACTION	1
#define DECODE_ACTION	2
#define DEFAULT_ACTION	1



FILE* getInFP(int fdin)
{
      FILE *fp = fdopen(fdin, "rb");
  
      if (fp == NULL) {
          perror("Failed to open input");
//          exit(1);
      }

	return fp;
}

FILE* getOutFP(int fdout)
{
   FILE *fpout  = {0};
  	
  	if(fdout==1){
  		fpout = stdout;
  	} else {
  
  		fpout = fdopen(fdout,"wb");

  		if (fpout == 0) {
//  		    fprintf(stderr, "Error - Cannot open output stream %d\n", fdout);
// 		    fprintf(stderr, "Program will close unexpectedly\n");
  		    exit(-1);
  		}
  	}
	
	return fpout;
}


void usage(char* pgname)
{
	fprintf(stdout,"Usage:\n");
	fprintf(stdout,"%s -h\n",pgname);
	fprintf(stdout,"%s -V\n",pgname);
	fprintf(stdout,"%s [options]\n",pgname);

	fprintf(stdout,"Options:\n");
	fprintf(stdout,"%s -V, --version\t\t\tPrint version and quit.\n",pgname);		
	fprintf(stdout,"%s -h, --help\t\t\tPrint this information.\n",pgname);

	fprintf(stdout,"%s -i, --input\t\t\tLocation of the input file.\n",pgname);
	fprintf(stdout,"%s -o, --output\t\t\tLocation of the output file.\n",pgname);
	fprintf(stdout,"%s -a, --action\t\t\tProgram action: encode(default) or decode\n",pgname);

	fprintf(stdout,"Examples:\n");
 
	fprintf(stdout,"%s -a encode -i ~/input -o ~/output\n",pgname);
	fprintf(stdout,"%s -a decode\n",pgname);
	
}

int main(int argc, char *argv[])
{
    int fdin=0;
    int fdout=1;
    int ch;

	static struct option longopts[] = {
             { "version", no_argument, NULL, 'V' },
             { "help", no_argument, NULL, 'h' },
             { "action", required_argument, NULL, 'a' },
             { "input", required_argument, NULL, 'i' },
             { "output", required_argument, NULL, 'o' },
	         { NULL, 0, NULL, 0 }
     };
	
    int action = DEFAULT_ACTION;

    while ((ch = getopt_long(argc, argv, "o:i:a:Vh", longopts, NULL)) != -1)
	{

         switch (ch) {
			case 'o': 
				if (*optarg!='-' && ((fdout = open(optarg, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)) == -1)) {
					fprintf(stderr, "unable to open %s\n", optarg);
		            usage(argv[0]);
					exit(1);
				}
				break;
			case 'i': 
				if (*optarg!='-' && ((fdin = open(optarg, O_RDONLY, 0)) == -1)) {
					fprintf(stderr, "unable to open %s\n", optarg);
		            usage(argv[0]);
					exit(1);
                }
                break;
			case 'a':
				if(strcmp(optarg, "encode")==0){
					action = ENCODE_ACTION;
				} else if(strcmp(optarg, "decode")==0){
					action = DECODE_ACTION;
				} else {
					fprintf(stderr, "Accion desconocida: %s\n", optarg);
					exit(1);
				}
				break;
            	
            case 'h': 
				usage(argv[0]);
				printf("cantidad de argumentos: %d\n", argc);
            	exit(0);	
      	    	break;
			case 'V':
            	printf("%s, version 1.1\n",argv[0]);	
            	exit(0);
      	    	break;	     
            default:
				fprintf(stderr, "DEFAULT %d\n", ch);
            	usage(argv[0]);
				exit(0);
				break;
         }

	}

	int salida = 0;

	//if(action ==  ENCODE_ACTION){
		salida = base64_encode(getInFP(fdin), getOutFP(fdout));
//	}
//	salida = base64_decode(fdin, fdout);

	// cierro los streams
	close(fdout);
    close(fdin);
	
	return salida;
}



